/******************************************************************************
* 文件名称: irq.c
* 内容摘要: 中断请求
* 创建者の: 孔佳伟
* 个人主页: https://gitee.com/openes
* 修改记录: 
******************************************************************************/

#include <irq.h>
#include <share.h>
#include <desc.h>
#include <interrupt.h>


/******************************************************************************
* 函数名称: IrqRegister(E_IRQ_NUM irqNmu, F_ISR ifunc)
* 功能说明: 注册中断服务程序
* 输入参数: E_IRQ_NUM irqNmu	--中断号
    　　　　F_ISR ifunc	        --中断服务程序
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET IrqRegister(E_IRQ_NUM irqNmu, F_ISR ifunc)
{
    // 检查参数合法性
    if(irqNmu >= IRQ_TOTAL || NULL == ifunc)
        return E_ERR;
    
    // 从共享内存中获取中段描述符表 IDT 地址 和大小
    GATE* gate = (GATE*)(*(U32*)IDT_ENTRY_ADDR);
    U32 idtSize = *((U32*)(IDT_SIZE_ADDR));

    // 合法性检查
    if(NULL == gate || 0 == idtSize || irqNmu >= idtSize)
        return E_ERR;

    // 函数名就相当于函数入口地址
    // 由于使用平坦模式，段基址为 0，那么函数名 func 地址就等同于段内偏移
    (gate+irqNmu)->offset1 = (U16)((U32)ifunc);
    (gate+irqNmu)->offset2 = (U16)(((U32)ifunc)>>16);

    return E_OK;
}

/******************************************************************************
* 函数名称: IrqInit(void)
* 功能说明: 将中断服务程序入口注册到 IDT 中
* 输入参数: 无
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 中断服务程序入口见 interrupt.asm
******************************************************************************/
E_RET IrqInit(void)
{
    E_IRQ_NUM irqNum = IRQ0;
    E_RET ret = E_ERR;
    U32 idtSize = *((U32*)(IDT_SIZE_ADDR));
    U32* isr = (U32*)&IntVectorStart;
    U32 isrSize = (U32)IntVectorLen;

    for(irqNum = IRQ0; irqNum < IRQ_TOTAL && irqNum < idtSize && irqNum < isrSize; irqNum++, isr++)
    {
        ret |= IrqRegister(irqNum, (F_ISR)(*isr));
    }
    return ret;
}